#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/list.h>
#include <asm/uaccess.h>
#include <linux/udp.h>
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>

#define PROCF_MAX_SIZE 1024
#define PROCF_NAME "minifirewall"

MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("Linux minifirewall");

MODULE_AUTHOR("Faraonii si Cleopatra");

unsigned long procf_buffer_pos;
char *procf_buffer;

static struct nf_hook_ops nfho;  //netfilter
static struct nf_hook_ops nfho_out;

//regula dupa care functioneaza firewall-ull.

struct regula_firewall
{
	unsigned char in_out; /*0:in sau out...1:in packet ....2:out packet*/
	unsigned int src_ip;
	unsigned int src_netmask;
	unsigned int src_port;  //0-95535
	unsigned int dest_ip;
	unsigned int dest_netmask;
	unsigned int dest_port;
	unsigned char proto; //tipul ptotocolului 0:all 1:tcp 2: udp
	unsigned char action; //defineste actiunea 0:block  1:unblock
	
	struct list_head list;
};

struct regula_firewall_bruta 
{
    unsigned char in_out;
    char *src_ip;
    char *src_netmask;
    char *src_port;
    char *dest_ip;
    char *dest_netmask;
    char *dest_port;
    unsigned char proto;
    unsigned char action;
};

//regula curenta dupa care actioneaza firewall-ul.
static struct regula_firewall regula;

unsigned int port_str_to_int(char *port_str)
{
    unsigned int port = 0;    
    int i = 0;
    if (port_str==NULL) 
	{
        return 0;
    }
    while (port_str[i]!='\0') 
	{
        port = port*10 + (port_str[i]-'0');
        i++;
    }
    return port;
}

void port_int_to_str(unsigned int port, char *port_str)
{
    sprintf(port_str, "%u", port);
}

//Convertim sirul ip deoarece functiile netfilter care extrag (decapsuleaza) dintr-un pachet header-ele au urmatorul format
//		static inline unsigned char *skb_mac_header(const struct sk_buff *skb);
//		static inline unsigned char *skb_network_header(const struct sk_buff *skb);
//		static inline unsigned char *skb_transport_header(const struct sk_buff *skb);
unsigned int ip_str_to_hl(char *ip_str) 
{
    /*converteste sirul intr-o matrice de biti: din "131.132.162.25" in [131][132][162][25]*/
    unsigned char ip_array[4];
    int i = 0;
    unsigned int ip = 0;
    if (ip_str==NULL) 
	{
        return 0; 
    }
    memset(ip_array, 0, 4);
    while (ip_str[i]!='.') 
	{
        ip_array[0] = ip_array[0]*10 + (ip_str[i++]-'0');
    }
    ++i;
    while (ip_str[i]!='.')
	{
        ip_array[1] = ip_array[1]*10 + (ip_str[i++]-'0');
	}
    ++i;
    while (ip_str[i]!='.')
	{
        ip_array[2] = ip_array[2]*10 + (ip_str[i++]-'0');
    }
    ++i;
    while (ip_str[i]!='\0')
	{
        ip_array[3] = ip_array[3]*10 + (ip_str[i++]-'0');
    }

    /*converteste din matricea de biti in formatul long*/
    ip = (ip_array[0] << 24);
    ip = (ip | (ip_array[1] << 16));
    ip = (ip | (ip_array[2] << 8));
    ip = (ip | ip_array[3]);
    //printk(KERN_INFO "ip_str_to_hl convert %s to %u\n", ip_str, ip);
    return ip;
}

void ip_hl_to_str(unsigned int ip, char *ip_str) 
{
	//Conversia inversa din matrice de biti in sir.
    unsigned char ip_array[4];
    memset(ip_array, 0, 4);
    ip_array[0] = (ip_array[0] | (ip >> 24));
    ip_array[1] = (ip_array[1] | (ip >> 16));
    ip_array[2] = (ip_array[2] | (ip >> 8));
    ip_array[3] = (ip_array[3] | ip);
    sprintf(ip_str, "%u.%u.%u.%u", ip_array[0], ip_array[1], ip_array[2], ip_array[3]);
}

bool check_ip(unsigned int ip, unsigned int ip_rule, unsigned int mask)
{
    unsigned int tmp = ntohl(ip);    //conversie ip
    int cmp_len = 32;
    int i = 0, j = 0;
    printk(KERN_INFO "compara ip: %u <=> %u\n", tmp, ip_rule);
    if (mask != 0) 
	{
       cmp_len = 0;
       for (i = 0; i < 32; ++i) 
	   {
		   if (mask & (1 << (32-1-i)))
				cmp_len++;
		   else
			   break;
       }
    }

    /*compara cele doua adrese IP*/
    for (i = 31, j = 0; j < cmp_len; --i, ++j) 
	{
        if ((tmp & (1 << i)) != (ip_rule & (1 << i))) 
		{
            printk(KERN_INFO "comparare ip: bitul %d nu se potriveste\n", (32-i));
            return false;
        }
	}
    return true;
}

void add_a_rule(struct regula_firewall_bruta* a_rule_desp) 
{
    struct regula_firewall* a_rule;
    a_rule = kmalloc(sizeof(*a_rule), GFP_KERNEL);
    if (a_rule == NULL) 
	{
        printk(KERN_INFO "eroare: nu poate aloca memorie pentru o noua regula\n");
        return;
    }
    a_rule->in_out = a_rule_desp->in_out;
    if (strcmp(a_rule_desp->src_ip, "-") != 0) 
        a_rule->src_ip = ip_str_to_hl(a_rule_desp->src_ip);
    else
        a_rule->src_ip = NULL;
    if (strcmp(a_rule_desp->src_netmask, "-") != 0)
        a_rule->src_netmask = ip_str_to_hl(a_rule_desp->src_netmask);
    else
        a_rule->src_netmask = NULL;
    if (strcmp(a_rule_desp->src_port, "-") != 0)
        a_rule->src_port = port_str_to_int(a_rule_desp->src_port);
    else 
        a_rule->src_port = NULL;
    if (strcmp(a_rule_desp->dest_ip, "-") != 0)
        a_rule->dest_ip = ip_str_to_hl(a_rule_desp->dest_ip);
    else 
        a_rule->dest_ip = NULL;
    if (strcmp(a_rule_desp->dest_netmask, "-") != 0)
	{
		a_rule->dest_netmask = ip_str_to_hl(a_rule_desp->dest_netmask);
	}
    else 
	{
		a_rule->dest_netmask = NULL;
	}
    if (strcmp(a_rule_desp->dest_port, "-") != 0)
        a_rule->dest_port = port_str_to_int(a_rule_desp->dest_port);
    else 
        a_rule->dest_port = NULL;
    a_rule->proto = a_rule_desp->proto;
    a_rule->action = a_rule_desp->action;
    printk(KERN_INFO "add_a_rule: in_out=%u, src_ip=%u, src_netmask=%u, src_port=%u, dest_ip=%u, dest_netmask=%u, dest_port=%u, proto=%u, action=%u\n", a_rule->in_out, a_rule->src_ip, a_rule->src_netmask, a_rule->src_port, a_rule->dest_ip, a_rule->dest_netmask, a_rule->dest_port, a_rule->proto, a_rule->action);
    INIT_LIST_HEAD(&(a_rule->list));
    list_add_tail(&(a_rule->list), &(regula.list));
}


void init_regula_firewall_bruta(struct regula_firewall_bruta* a_rule_desp) 
{
    a_rule_desp->in_out = 0;
    a_rule_desp->src_ip = (char *)kmalloc(16, GFP_KERNEL);
    a_rule_desp->src_netmask = (char *)kmalloc(16, GFP_KERNEL);
    a_rule_desp->src_port = (char *)kmalloc(16, GFP_KERNEL);
    a_rule_desp->dest_ip = (char *)kmalloc(16, GFP_KERNEL);
    a_rule_desp->dest_netmask = (char *)kmalloc(16, GFP_KERNEL);
    a_rule_desp->dest_port = (char *)kmalloc(16, GFP_KERNEL);
    a_rule_desp->proto = 0;
    a_rule_desp->action = 0;
}

void delete_a_rule(int num) 
{
    int i = 0;
    struct list_head *p, *q;
    struct regula_firewall *a_rule;
    printk(KERN_INFO "sterge o regula: %d\n", num);
    list_for_each_safe(p, q, &regula.list) 
	{
        ++i;
        if (i == num) 
		{
            a_rule = list_entry(p, struct regula_firewall, list);
            list_del(p);
            kfree(a_rule);
            return;
        }
    }
}

int procf_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data)
{
	int ret;
	struct regula_firewall *a_rule;
	char token[20];
	printk(KERN_INFO "s-a apelat procf_read  \n", PROCF_NAME);
    if (offset > 0)
	{
        printk(KERN_INFO "nu este nimic de citit\n");
        *eof = 1;
        return 0;
    }
	else 
	{
		procf_buffer_pos = 0;
        ret = 0;
        list_for_each_entry(a_rule, &regula.list, list) 
		{
            if (a_rule->in_out==1) 
			{
                strcpy(token, "in");
            } 
			else 
				if (a_rule->in_out==2) 
				{
					strcpy(token, "out");
				}
            printk(KERN_INFO "token: %s\n", token);
            memcpy(procf_buffer + procf_buffer_pos, token, strlen(token));
            procf_buffer_pos += strlen(token);
            memcpy(procf_buffer + procf_buffer_pos, " ", 1);
            procf_buffer_pos++;

            //src ip
            if (a_rule->src_ip == NULL) 
			{
                strcpy(token, "-");
            } 
			else
			{
                ip_hl_to_str(a_rule->src_ip, token);
            } 
            printk(KERN_INFO "token: %s\n", token);
            memcpy(procf_buffer + procf_buffer_pos, token, strlen(token));
            procf_buffer_pos += strlen(token);
            memcpy(procf_buffer + procf_buffer_pos, " ", 1);
            procf_buffer_pos++;

            //src netmask
            if (a_rule->src_netmask==NULL) 
			{
                strcpy(token, "-");
            } 
			else 
			{
                ip_hl_to_str(a_rule->src_netmask, token);
            } 
            printk(KERN_INFO "token: %s\n", token);
            memcpy(procf_buffer + procf_buffer_pos, token, strlen(token));
            procf_buffer_pos += strlen(token);
            memcpy(procf_buffer + procf_buffer_pos, " ", 1);
            procf_buffer_pos++;

            //src port
            if (a_rule->src_port==0) 
			{
                strcpy(token, "-");
            } 
			else 
			{
                port_int_to_str(a_rule->src_port, token);
            } 
            printk(KERN_INFO "token: %s\n", token);
            memcpy(procf_buffer + procf_buffer_pos, token, strlen(token));
            procf_buffer_pos += strlen(token);
            memcpy(procf_buffer + procf_buffer_pos, " ", 1);
            procf_buffer_pos++;

            //dest ip
            if (a_rule->dest_ip==NULL) 
			{
                strcpy(token, "-");
            }
			else 
			{
                ip_hl_to_str(a_rule->dest_ip, token);
            } 
            printk(KERN_INFO "token: %s\n", token);
            memcpy(procf_buffer + procf_buffer_pos, token, strlen(token));
            procf_buffer_pos += strlen(token);
            memcpy(procf_buffer + procf_buffer_pos, " ", 1);
            procf_buffer_pos++;
            //dest netmask
            if (a_rule->dest_netmask==NULL) 
			{
                strcpy(token, "-");
            }
			else 
			{
                ip_hl_to_str(a_rule->dest_netmask, token);
            } 
            printk(KERN_INFO "token: %s\n", token);
            memcpy(procf_buffer + procf_buffer_pos, token, strlen(token));
            procf_buffer_pos += strlen(token);
            memcpy(procf_buffer + procf_buffer_pos, " ", 1);
            procf_buffer_pos++;
            //dest port
            if (a_rule->dest_port==0) 
			{
                strcpy(token, "-");
            } 
			else 
			{
                port_int_to_str(a_rule->dest_port, token);
            } 
            printk(KERN_INFO "token: %s\n", token);
            memcpy(procf_buffer + procf_buffer_pos, token, strlen(token));
            procf_buffer_pos += strlen(token);
            memcpy(procf_buffer + procf_buffer_pos, " ", 1);
            procf_buffer_pos++;
            //protocol
            if (a_rule->proto==0) 
			{
                strcpy(token, "ALL");
            } 
			else
				if (a_rule->proto==1) 
				{
					strcpy(token, "TCP");
				}  
				else 
					if (a_rule->proto==2) 
					{
						strcpy(token, "UDP");
					}
            printk(KERN_INFO "token: %s\n", token);
            memcpy(procf_buffer + procf_buffer_pos, token, strlen(token));
            procf_buffer_pos += strlen(token);
            memcpy(procf_buffer + procf_buffer_pos, " ", 1);
            procf_buffer_pos++;
            //action
            if (a_rule->action==0)
			{
                strcpy(token, "BLOCK");
            } 
			else 
				if (a_rule->action==1)
				{
					strcpy(token, "UNBLOCK");
				}
            printk(KERN_INFO "token: %s\n", token);
            memcpy(procf_buffer + procf_buffer_pos, token, strlen(token));
            procf_buffer_pos += strlen(token);
            memcpy(procf_buffer + procf_buffer_pos, "\n", 1);
            procf_buffer_pos++;
        }
	 memcpy(buffer, procf_buffer, procf_buffer_pos);
     ret = procf_buffer_pos;
	}
	return ret; 	
	}


int procf_write(struct file *file, const char *buffer, unsigned long count, void *data)
{
   int i, j;
   struct regula_firewall_bruta *rule_desp;
   printk(KERN_INFO "s-a apelat procf_write.\n");

 

   /*citest continutul in buffer*/

 

   procf_buffer_pos = 0;

 

   printk(KERN_INFO "pos: %ld; count: %ld\n", procf_buffer_pos, count);

 

   if (procf_buffer_pos + count > PROCF_MAX_SIZE) {

 

       count = PROCF_MAX_SIZE-procf_buffer_pos;

 

   } 

 

   if (copy_from_user(procf_buffer+procf_buffer_pos, buffer, count)) {

 

       return -EFAULT;

 

   }

 

   if (procf_buffer[procf_buffer_pos] == 'p') {

 

       //print command

 

       return 0;

 

   } else if (procf_buffer[procf_buffer_pos] == 'd') {

 

       //delete command

 

       i = procf_buffer_pos+1; j = 0;

 

       while ((procf_buffer[i]!=' ') && (procf_buffer[i]!='\n') ) {

 

           printk(KERN_INFO "delete: %d\n", procf_buffer[i]-'0');

 

           j = j*10 + (procf_buffer[i]-'0');

 

           ++i;

 

       }

 

       printk(KERN_INFO "sterge o regula: %d\n", j);

 

       delete_a_rule(j);

 

       return count;

 

   }

 

   /*adauga o noua regula*/

   rule_desp = kmalloc(sizeof(*rule_desp), GFP_KERNEL);

   if (rule_desp == NULL) {

       printk(KERN_INFO "eroare la alocarea dinamica\n");

       return -ENOMEM;

   }

 

   init_regula_firewall_bruta(rule_desp);

 

   

 

   /**completeaza campurile noii reguli **/

 

   /***in_out***/

 

   i = procf_buffer_pos; j = 0;

 

   if (procf_buffer[i]!=' ') {

 

       rule_desp->in_out = (unsigned char)(procf_buffer[i++] - '0');

 

   }

 

   ++i;

 

   printk(KERN_INFO "in or out: %u\n", rule_desp->in_out);

 

   /***src ip***/

 

   j = 0;

 

   while (procf_buffer[i]!=' ') {

 

       rule_desp->src_ip[j++] = procf_buffer[i++];

 

   }

 

   ++i;

 

   rule_desp->src_ip[j] = '\0';

 

   printk(KERN_INFO "src ip: %s\n", rule_desp->src_ip);

 

   /***src netmask***/

 

   j = 0;

 

   while (procf_buffer[i]!=' ') {

 

       rule_desp->src_netmask[j++] = procf_buffer[i++];

 

   }

 

   ++i;

 

   rule_desp->src_netmask[j] = '\0';

 

   printk(KERN_INFO "src netmask: %s\n", rule_desp->src_netmask);

 

   /***src port number***/

 

   j = 0;

 

   while (procf_buffer[i]!=' ') {

 

       rule_desp->src_port[j++] = procf_buffer[i++];

 

   }

 

   ++i;

 

   rule_desp->src_port[j] = '\0';

 

   printk(KERN_INFO "src_port: %s\n", rule_desp->src_port);

 

   /***dest ip***/

 

   j = 0;

 

   while (procf_buffer[i]!=' ') {

 

       rule_desp->dest_ip[j++] = procf_buffer[i++];

 

   }

 

   ++i;

 

   rule_desp->dest_ip[j] = '\0';

 

   printk(KERN_INFO "dest ip: %s\n", rule_desp->dest_ip);

 

   /***dest netmask***/

 

   j = 0;

 

   while (procf_buffer[i]!=' ') {

 

       rule_desp->dest_netmask[j++] = procf_buffer[i++];

 

   }

 

   ++i;

 

   rule_desp->dest_netmask[j] = '\0';

 

   printk(KERN_INFO "dest netmask%s\n", rule_desp->dest_netmask);

 

   /***dest port***/

 

   j = 0;

 

   while (procf_buffer[i]!=' ') {

 

       rule_desp->dest_port[j++] = procf_buffer[i++];

 

   }

 

   ++i;

 

   rule_desp->dest_port[j] = '\0';

 

   printk(KERN_INFO "dest port: %s\n", rule_desp->dest_port);

 

   /***proto***/

 

   j = 0;

 

   if (procf_buffer[i]!=' ') {

       if (procf_buffer[i] != '-')

 

           rule_desp->proto = (unsigned char)(procf_buffer[i++]-'0');

       else

           ++i;

 

   }

 

   ++i;

 

   printk(KERN_INFO "proto: %d\n", rule_desp->proto);

 

   /***action***/

 

   j = 0;

   if (procf_buffer[i]!=' ') {

       if (procf_buffer[i] != '-')

 

           rule_desp->action = (unsigned char)(procf_buffer[i++]-'0');

       else

           ++i;

 

   }

 

   ++i;

 

   printk(KERN_INFO "action: %d\n", rule_desp->action);

   add_a_rule(rule_desp);

   kfree(rule_desp);

 

   printk(KERN_INFO "--------------------\n");

 

   return count;

 

}

 

//functia care va face hooking-ul pentru pachetele care ies.
 

unsigned int hook_func_out(unsigned int hooknum, struct sk_buff *skb, 

 

        const struct net_device *in, const struct net_device *out,

 

        int (*okfn)(struct sk_buff *)) {


 

   struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);

 

   struct udphdr *udp_header;

 

   struct tcphdr *tcp_header;

 

   struct list_head *p;

 

   struct regula_firewall *a_rule;

   char src_ip_str[16], dest_ip_str[16];

 

   int i = 0;

 

   unsigned int src_ip = (unsigned int)ip_header->saddr;

 

   unsigned int dest_ip = (unsigned int)ip_header->daddr;

 

   unsigned int src_port = 0;

 

   unsigned int dest_port = 0;


 

   if (ip_header->protocol==17) {

 

       udp_header = (struct udphdr *)skb_transport_header(skb);

 

       src_port = (unsigned int)ntohs(udp_header->source);

 

       dest_port = (unsigned int)ntohs(udp_header->dest);

 

   } else if (ip_header->protocol == 6) {

 

       tcp_header = (struct tcphdr *)skb_transport_header(skb);

 

       src_port = (unsigned int)ntohs(tcp_header->source);

 

       dest_port = (unsigned int)ntohs(tcp_header->dest);

 

   }

   ip_hl_to_str(ntohl(src_ip), src_ip_str);

   ip_hl_to_str(ntohl(dest_ip), dest_ip_str);

 

   printk(KERN_INFO "OUT packet info: src ip: %u = %s, src port: %u; dest ip: %u = %s, dest port: %u; proto: %u\n", src_ip, src_ip_str, src_port, dest_ip, dest_ip_str, dest_port, ip_header->protocol); 

 
   //verifica daca in firewall exista vreo potrivire.
   //in cazul in care exista mai multe reguli care se potrivesc ia-o va fi folosita prima.

 

   list_for_each(p, &regula.list) {

 

       i++;

 

       a_rule = list_entry(p, struct regula_firewall, list);

       //printk(KERN_INFO "rule %d: a_rule->in_out = %u; a_rule->src_ip = %u; a_rule->src_netmask=%u; a_rule->src_port=%u; a_rule->dest_ip=%u; a_rule->dest_netmask=%u; a_rule->dest_port=%u; a_rule->proto=%u; a_rule->action=%u\n", i, a_rule->in_out, a_rule->src_ip, a_rule->src_netmask, a_rule->src_port, a_rule->dest_ip, a_rule->dest_netmask, a_rule->dest_port, a_rule->proto, a_rule->action);

 

       //daca o regula nu este marcata ca fiind "out", ea va fi omisa

 

       if (a_rule->in_out != 2) {

 

           printk(KERN_INFO "regula %d (a_rule->in_out: %u)nu se potriveste\n", i, a_rule->in_out);

 

           continue;

 

       } else {

 

           //verifca protocol

 

           if ((a_rule->proto==1) && (ip_header->protocol != 6)) {

 

               printk(KERN_INFO "regula %d nu se potriveste \n", i);

 

               continue;

 

           } else if ((a_rule->proto==2) && (ip_header->protocol != 17)) {

 

               printk(KERN_INFO "regula %d nu se potriveste \n", i);

 

               continue;

 

           }

 

           //verifica adresa ip

 

           if (a_rule->src_ip==0) {

 

              //regula nu specifica ip-ul, deci se potrivest

 

           } else {

 

              if (!check_ip(src_ip, a_rule->src_ip, a_rule->src_netmask)) {

 

                  printk(KERN_INFO "regula %d nu se potriveste: nu se potriveste cu ip-ul sursa\n", i);

 

                  continue;

 

              }

 

           }

 

           if (a_rule->dest_ip == 0) {

 

               //regula nu specifica ip-ul, deci potrivire.

 

           } else {

 

               if (!check_ip(dest_ip, a_rule->dest_ip, a_rule->dest_netmask)) {

 

                   printk(KERN_INFO "regula %d nu se potriveste\n", i);

 

                   continue;

 

               }

 

           }

 

           //verifica numarul portului.

 

           if (a_rule->src_port==0) {

 

               //regula nu specifica numarul portului, deci se potriveste

 

           } else if (src_port!=a_rule->src_port) {

 

               printk(KERN_INFO "regula %d nu se potriveste\n", i);

 

               continue;

 

           }

 

           if (a_rule->dest_port == 0) {

 

               //regula nu specifica numarul portului, deci se potriveste

 

           }

 

           else if (dest_port!=a_rule->dest_port) {

 

               printk(KERN_INFO "regula %d nu se potriveste\n", i);

 

               continue;

 

           }

 

           //a fost gasita o potrivire, actioneaza conform campului action: BLOCK, UNBLOCK

 

           if (a_rule->action==0) {

 

               printk(KERN_INFO "s-a facut o potrivire: %d arunca pachetul\n", i);

 

              printk(KERN_INFO "---------------------------------------\n");

 

               return NF_DROP;

 

           } else {

 

               printk(KERN_INFO "s-a facut o potrivire: %d accepta pachetul\n", i);

 

              printk(KERN_INFO "---------------------------------------\n");

 

               return NF_ACCEPT;

 

           }

 

       }

 

   }

 

   printk(KERN_INFO "nicio potrivire, accepta pachetul\n");

 

   printk(KERN_INFO "---------------------------------------\n");

 

   return NF_ACCEPT;            

 

}

 

 

 

 

 

//functia de hooking pentru pachetele de intrare.

 

unsigned int hook_func_in(unsigned int hooknum, struct sk_buff *skb, 

 

        const struct net_device *in, const struct net_device *out,

 

        int (*okfn)(struct sk_buff *)) {


 

   struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);

 

   struct udphdr *udp_header;

 

   struct tcphdr *tcp_header;

 

   struct list_head *p;

 

   struct regula_firewall *a_rule;

   char src_ip_str[16], dest_ip_str[16];

 

   int i = 0;

 

   unsigned int src_ip = (unsigned int)ip_header->saddr;

 

   unsigned int dest_ip = (unsigned int)ip_header->daddr;

 

   unsigned int src_port = 0;

 

   unsigned int dest_port = 0;

 

   if (ip_header->protocol==17) {

 

       udp_header = (struct udphdr *)(skb_transport_header(skb)+20);

 

       src_port = (unsigned int)ntohs(udp_header->source);

 

       dest_port = (unsigned int)ntohs(udp_header->dest);

 

   } else if (ip_header->protocol == 6) {

 

       tcp_header = (struct tcphdr *)(skb_transport_header(skb)+20);

 

       src_port = (unsigned int)ntohs(tcp_header->source);

 

       dest_port = (unsigned int)ntohs(tcp_header->dest);

 

   }

   ip_hl_to_str(ntohl(src_ip), src_ip_str);

   ip_hl_to_str(ntohl(dest_ip), dest_ip_str);

 

   printk(KERN_INFO "IN packet info: src ip: %u = %s, src port: %u; dest ip: %u = %s, dest port: %u; proto: %u\n", src_ip, src_ip_str, src_port, dest_ip, dest_ip_str, dest_port, ip_header->protocol); 

 

   list_for_each(p, &regula.list) {

 

       i++;

 

       a_rule = list_entry(p, struct regula_firewall, list);

//printk(KERN_INFO "rule %d: a_rule->in_out = %u; a_rule->src_ip = %u; a_rule->src_netmask=%u; a_rule->src_port=%u; a_rule->dest_ip=%u; a_rule->dest_netmask=%u; a_rule->dest_port=%u; a_rule->proto=%u; a_rule->action=%u\n", i, a_rule->in_out, a_rule->src_ip, a_rule->src_netmask, a_rule->src_port, a_rule->dest_ip, a_rule->dest_netmask, a_rule->dest_port, a_rule->proto, a_rule->action);


 

       if (a_rule->in_out != 1) {

 

           printk(KERN_INFO "regula %d (a_rule->in_out:%u) nu se potriveste \n", i, a_rule->in_out);

 

           continue;

 

       } else {

 

           if ((a_rule->proto==1) && (ip_header->protocol != 6)) {

 

               printk(KERN_INFO "regula nu  se potriveste\n", i);

 

               continue;

 

           } else if ((a_rule->proto==2) && (ip_header->protocol != 17)) {

 

               printk(KERN_INFO "regula nu  se potriveste\n", i);

 

               continue;

 

           }

 

           if (a_rule->src_ip==0) {

 

              //

 

           } else {

 

              if (!check_ip(src_ip, a_rule->src_ip, a_rule->src_netmask)) {

 

                   printk(KERN_INFO "regula nu  se potriveste\n", i);

 

                  continue;

 

              }

 

           }

 

           if (a_rule->dest_ip == 0) {

 

               //

 

           } else {

 

               if (!check_ip(dest_ip, a_rule->dest_ip, a_rule->dest_netmask)) {

 

                   printk(KERN_INFO "regula nu  se potriveste\n", i);               

 

                  continue;

 

               }

 

           }


 

           if (a_rule->src_port==0) {
			   //potrivire

 

           } else if (src_port!=a_rule->src_port) {
			    printk(KERN_INFO "regula nu  se potriveste\n", i);

 

               continue;

 

           }

 

           if (a_rule->dest_port == 0) {
			   //potrivire

 

           }

 

           else if (dest_port!=a_rule->dest_port) {
			    printk(KERN_INFO "regula nu  se potriveste\n", i);

 

               continue;

 

           }

 

           //a fost gasita o potrivire, actioneaza in consecinta.

 

           if (a_rule->action==0) {

 

               printk(KERN_INFO "o potrivire %d, arunca pachetul\n", i);

 

               printk(KERN_INFO "---------------------------------------\n");

 

               return NF_DROP;

 

           } else {

 

               printk(KERN_INFO "a fost gasita o potrivire %d, accepta pachetul\n", i);

 

               printk(KERN_INFO "---------------------------------------\n");

 

               return NF_ACCEPT;

 

           }

 

       }

 

   }

 

   printk(KERN_INFO "nicio potrivire accepta pachetul\n");

 

   printk(KERN_INFO "---------------------------------------\n");

 

   return NF_ACCEPT;                

 

}

 

/* rutina de initializare */


struct file_operations proc_fops = {
		read: procf_read,
		write: procf_write
};


void create_new_proc_entry(void) 
{
	proc_create(PROCF_NAME,0,NULL,&proc_fops);
}


int proc_init(void) {

    printk(KERN_INFO "initializeaza modul kernel\n");

    procf_buffer = (char *) vmalloc(PROCF_MAX_SIZE);


    INIT_LIST_HEAD(&(regula.list));

    
	create_new_proc_entry();

    printk(KERN_INFO "/proc/%s is created\n", PROCF_NAME);

 

    nfho.hook = hook_func_in;

 

    nfho.hooknum = NF_INET_LOCAL_IN;

 

    nfho.pf = PF_INET;

 

    nfho.priority = NF_IP_PRI_FIRST;

 

    nf_register_hook(&nfho);        

 

    nfho_out.hook = hook_func_out;

 

    nfho_out.hooknum = NF_INET_LOCAL_OUT;

 

    nfho_out.pf = PF_INET;

 

    nfho_out.priority = NF_IP_PRI_FIRST;

 

    nf_register_hook(&nfho_out);   

    return 0;

}

 

/*Rutina de cleanup */

void proc_cleanup(void){

    struct list_head *p, *q;

    struct regula_firewall *a_rule;

    nf_unregister_hook(&nfho);

 

    nf_unregister_hook(&nfho_out);

    printk(KERN_INFO "lista de reguli goala\n");

    list_for_each_safe(p, q, &regula.list) {

        printk(KERN_INFO "libera\n");

        a_rule = list_entry(p, struct regula_firewall, list);

        list_del(p);

        kfree(a_rule);

    }

    remove_proc_entry(PROCF_NAME, NULL);

    printk(KERN_INFO "modul kernel indepartat.\n");
}


module_init(proc_init);
module_exit(proc_cleanup);






